home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2002 #3 / Amiga Plus CD - 2002 - No. 03.iso / AmigaPlus / Demos / fxPAINT_Demo / InstallData / Amithlon / run_elf-1.7 / src / elfloader.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-11-13  |  30.1 KB  |  1,173 lines

  1. /*
  2.      RUN_ELF - Load and execute big endian ix86 ELF binaries
  3.      Copyright (C) 2001-2002 Martin Blom <martin@blom.org>
  4.      
  5.      This program is free software; you can redistribute it and/or
  6.      modify it under the terms of the GNU General Public License
  7.      as published by the Free Software Foundation; either version 2
  8.      of the License, or (at your option) any later version.
  9.      
  10.      This program is distributed in the hope that it will be useful,
  11.      but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.      GNU General Public License for more details.
  14.      
  15.      You should have received a copy of the GNU General Public License
  16.      along with this program; if not, write to the Free Software
  17.      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18. */
  19.  
  20. /*
  21. ** Based on code from the ppc.library emulator by Frank Wille:
  22. ** ppc.library emulation
  23. ** (c)1998-99 Frank Wille <frank@phoenix.owl.de>
  24. */
  25.  
  26. #include <exec/types.h>
  27. #include <exec/memory.h>
  28. #include <exec/nodes.h>
  29. #include <dos/dos.h>
  30. #include <proto/dos.h>
  31. #include <proto/exec.h>
  32.  
  33. #include <string.h>
  34.  
  35. #include "elfloader.h"
  36.  
  37. void
  38. KPrintFArgs( UBYTE* fmt, 
  39.              ULONG* args );
  40.  
  41. #define KPrintF( fmt, ... )        \
  42. ({                                 \
  43.   ULONG _args[] = { __VA_ARGS__ }; \
  44.   KPrintFArgs( (fmt), _args );     \
  45. })
  46.  
  47. void
  48. ReqA( const char* text, APTR args );
  49.  
  50. #define Req( fmt, ... )            \
  51. ({                                 \
  52.   ULONG _args[] = { __VA_ARGS__ }; \
  53.   ReqA( (fmt), _args );            \
  54. })
  55.  
  56.  
  57. #define bswap_long(x) \
  58.      ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >>  8) | \
  59.       (((x) & 0x0000ff00) <<  8) | (((x) & 0x000000ff) << 24))
  60.  
  61. #define bswap_short(x) \
  62.      ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))
  63.  
  64.  
  65. /*** From glibc2/elf.h *******************************************************/
  66.  
  67. /* Intel 80386 specific definitions.  */
  68.  
  69. /* i386 relocs.  */
  70.  
  71. #define R_386_NONE      0               /* No reloc */
  72. #define R_386_32        1               /* Direct 32 bit  */
  73. #define R_386_PC32      2               /* PC relative 32 bit */
  74. #define R_386_GOT32     3               /* 32 bit GOT entry */
  75. #define R_386_PLT32     4               /* 32 bit PLT address */
  76. #define R_386_COPY      5               /* Copy symbol at runtime */
  77. #define R_386_GLOB_DAT  6               /* Create GOT entry */
  78. #define R_386_JMP_SLOT  7               /* Create PLT entry */
  79. #define R_386_RELATIVE  8               /* Adjust by program base */
  80. #define R_386_GOTOFF    9               /* 32 bit offset to GOT */
  81. #define R_386_GOTPC     10              /* 32 bit PC relative offset to GOT */
  82. /* Keep this the last entry.  */
  83. #define R_386_NUM       11
  84.  
  85.  
  86. /*** elfcommon.h *************************************************************/
  87.  
  88. /* e_indent indexes */
  89. #define EI_NIDENT  16
  90. #define EI_MAG0    0
  91. #define EI_MAG1    1
  92. #define EI_MAG2    2
  93. #define EI_MAG3    3
  94. #define EI_CLASS   4
  95. #define EI_DATA    5
  96. #define EI_VERSION 6
  97. #define EI_PAD     7
  98.  
  99. /* EI_CLASS */
  100. #define ELFCLASSNONE 0
  101. #define ELFCLASS32   1
  102. #define ELFCLASS64   2
  103.  
  104. /* EI_DATA */
  105. #define ELFDATANONE 0
  106. #define ELFDATA2LSB 1
  107. #define ELFDATA2MSB 2
  108.  
  109. /* e_type */
  110. #define ET_NONE   0                 /* No file type */
  111. #define ET_REL    1                 /* Relocatable file */
  112. #define ET_EXEC   2                 /* Executable file */
  113. #define ET_DYN    3                 /* Shared object file */
  114. #define ET_CORE   4                 /* Core file */
  115. #define ET_LOPROC 0xFF00            /* Processor-specific */
  116. #define ET_HIPROC 0xFFFF            /* Processor-specific */
  117.  
  118. /* e_version */
  119. #define EV_NONE    0
  120. #define EV_CURRENT 1
  121.  
  122. /* e_machine */
  123. #define EM_NONE           0
  124. #define EM_M32            1
  125. #define EM_SPARC          2
  126. #define EM_386            3
  127. #define EM_68K            4
  128. #define EM_88K            5
  129. #define EM_860            7
  130. #define EM_MIPS           8
  131. #define EM_MIPS_RS4_BE    10
  132. #define EM_SPARC64        11
  133. #define EM_PARISC         15
  134. #define EM_PPC_OLD        17
  135. #define EM_SPARC32PLUS    18
  136. #define EM_PPC            20
  137. #define EM_CYGNUS_POWERPC 0x9025
  138. #define EM_ALPHA          0x9026
  139.  
  140. /* values for program header, p_type field */
  141. #define PT_NULL    0                /* Program header table entry unused */
  142. #define PT_LOAD    1                /* Loadable program segment */
  143. #define PT_DYNAMIC 2                /* Dynamic linking information */
  144. #define PT_INTERP  3                /* Program interpreter */
  145. #define PT_NOTE    4                /* Auxiliary information */
  146. #define PT_SHLIB   5                /* Reserved, unspecified semantics */
  147. #define PT_PHDR    6                /* Entry for header table itself */
  148. #define PT_LOPROC  0x70000000       /* Processor-specific */
  149. #define PT_HIPROC  0x7FFFFFFF       /* Processor-specific */
  150.  
  151. /* Program segment permissions, in program header p_flags field */
  152. #define PF_X        (1 << 0)        /* Segment is executable */
  153. #define PF_W        (1 << 1)        /* Segment is writable */
  154. #define PF_R        (1 << 2)        /* Segment is readable */
  155. #define PF_MASKPROC 0xF0000000      /* Processor-specific reserved bits */
  156.  
  157. /* special sections indexes */
  158. #define SHN_UNDEF 0
  159. #define SHN_ABS 0xfff1
  160. #define SHN_COMMON 0xfff2
  161.  
  162. /* sh_type */
  163. #define SHT_NULL        0           /* Section header table entry unused */
  164. #define SHT_PROGBITS    1           /* Program specific (private) data */
  165. #define SHT_SYMTAB      2           /* Link editing symbol table */
  166. #define SHT_STRTAB      3           /* A string table */
  167. #define SHT_RELA        4           /* Relocation entries with addends */
  168. #define SHT_HASH        5           /* A symbol hash table */
  169. #define SHT_DYNAMIC     6           /* Information for dynamic linking */
  170. #define SHT_NOTE        7           /* Information that marks file */
  171. #define SHT_NOBITS      8           /* Section occupies no space in file */
  172. #define SHT_REL         9           /* Relocation entries, no addends */
  173. #define SHT_SHLIB       10          /* Reserved, unspecified semantics */
  174. #define SHT_DYNSYM      11          /* Dynamic linking symbol table */
  175. #define SHT_LOPROC      0x70000000  /* Processor-specific semantics, lo */
  176. #define SHT_HIPROC      0x7FFFFFFF  /* Processor-specific semantics, hi */
  177. #define SHT_LOUSER      0x80000000  /* Application-specific semantics */
  178. #define SHT_HIUSER      0x8FFFFFFF  /* Application-specific semantics */
  179.  
  180. /* sh_flags */
  181. #define SHF_WRITE     (1 << 0)      /* Writable data during execution */
  182. #define SHF_ALLOC     (1 << 1)      /* Occupies memory during execution */
  183. #define SHF_EXECINSTR (1 << 2)      /* Executable machine instructions */
  184. #define SHF_MASKPROC  0xF0000000    /* Processor-specific semantics */
  185.  
  186. /* Values of note segment descriptor types for core files. */
  187. #define NT_PRSTATUS 1               /* Contains copy of prstatus struct */
  188. #define NT_FPREGSET 2               /* Contains copy of fpregset struct */
  189. #define NT_PRPSINFO 3               /* Contains copy of prpsinfo struct */
  190.  
  191. #define STN_UNDEF 0                 /* undefined symbol index */
  192.  
  193. /* ST_BIND */
  194. #define STB_LOCAL  0                /* Symbol not visible outside obj */
  195. #define STB_GLOBAL 1                /* Symbol visible outside obj */
  196. #define STB_WEAK   2                /* Like globals, lower precedence */
  197. #define STB_LOPROC 13               /* Application-specific semantics */
  198. #define STB_HIPROC 15               /* Application-specific semantics */
  199.  
  200. /* ST_TYPE */
  201. #define STT_NOTYPE  0               /* Symbol type is unspecified */
  202. #define STT_OBJECT  1               /* Symbol is a data object */
  203. #define STT_FUNC    2               /* Symbol is a code object */
  204. #define STT_SECTION 3               /* Symbol associated with a section */
  205. #define STT_FILE    4               /* Symbol gives a file name */
  206. #define STT_LOPROC  13              /* Application-specific semantics */
  207. #define STT_HIPROC  15              /* Application-specific semantics */
  208.  
  209. /* Dynamic section tags */
  210. #define DT_NULL     0
  211. #define DT_NEEDED   1
  212. #define DT_PLTRELSZ 2
  213. #define DT_PLTGOT   3
  214. #define DT_HASH     4
  215. #define DT_STRTAB   5
  216. #define DT_SYMTAB   6
  217. #define DT_RELA     7
  218. #define DT_RELASZ   8
  219. #define DT_RELAENT  9
  220. #define DT_STRSZ    10
  221. #define DT_SYMENT   11
  222. #define DT_INIT     12
  223. #define DT_FINI     13
  224. #define DT_SONAME   14
  225. #define DT_RPATH    15
  226. #define DT_SYMBOLIC 16
  227. #define DT_REL      17
  228. #define DT_RELSZ    18
  229. #define DT_RELENT   19
  230. #define DT_PLTREL   20
  231. #define DT_DEBUG    21
  232. #define DT_TEXTREL  22
  233. #define DT_JMPREL   23
  234. #define DT_LOPROC   0x70000000
  235. #define DT_HIPROC   0x7fffffff
  236.  
  237. /*** elf32.h *****************************************************************/
  238.  
  239. typedef unsigned char uint8;
  240. typedef unsigned short uint16;
  241. typedef unsigned long uint32;
  242.  
  243.  
  244. struct Elf32_Ehdr {
  245.   unsigned char e_ident[EI_NIDENT];
  246.   uint16 e_type;
  247.   uint16 e_machine;
  248.   uint32 e_version;
  249.   uint32 e_entry;
  250.   uint32 e_phoff;
  251.   uint32 e_shoff;
  252.   uint32 e_flags;
  253.   uint16 e_ehsize;
  254.   uint16 e_phentsize;
  255.   uint16 e_phnum;
  256.   uint16 e_shentsize;
  257.   uint16 e_shnum;
  258.   uint16 e_shstrndx;
  259. };
  260.  
  261. struct Elf32_Shdr {
  262.   uint32 sh_name;
  263.   uint32 sh_type;
  264.   uint32 sh_flags;
  265.   uint32 sh_addr;
  266.   uint32 sh_offset;
  267.   uint32 sh_size;
  268.   uint32 sh_link;
  269.   uint32 sh_info;
  270.   uint32 sh_addralign;
  271.   uint32 sh_entsize;
  272. };
  273.  
  274. struct Elf32_Sym {
  275.   uint32 st_name;
  276.   uint32 st_value;
  277.   uint32 st_size;
  278.   uint8 st_info;
  279.   uint8 st_other;
  280.   uint16 st_shndx;
  281. };
  282.  
  283. /* st_info */
  284. #define ELF32_ST_BIND(i) ((i)>>4)
  285. #define ELF32_ST_TYPE(i) ((i)&0xf)
  286. #define ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf))
  287.  
  288. struct Elf32_Rel {
  289.   uint32 r_offset;
  290.   uint32 r_info;
  291. };
  292.  
  293. struct Elf32_Rela {
  294.   uint32 r_offset;
  295.   uint32 r_info;
  296.   uint32 r_addend;
  297. };
  298.  
  299. /* r_info */
  300. #define ELF32_R_SYM(i) ((i)>>8)
  301. #define ELF32_R_TYPE(i) ((unsigned char)(i))
  302. #define ELF32_R_INFO(s,t) (((s)<<8)+(unsigned char)(t))
  303.  
  304. /*** elfobject.h *************************************************************/
  305.  
  306. struct ELFSection {                     /* prog. sections for new tasks */
  307.   char *name;
  308.   APTR address;                         /* physical RAM address or NULL */
  309.   UWORD flags;
  310.   UWORD alignment;
  311.   long offset;                          /* file offset and section size */
  312.   ULONG size;
  313.   int nrel;                             /* number of relocs */
  314.   struct Elf32_Rela *relocs;            /* array of Elf32_Rela structs */
  315. };
  316.  
  317. #define ElfSecB_NOBITS          0       /* bss section */
  318. #define ElfSecF_NOBITS          1
  319. #define ElfSecB_RELA            1       /* Relocs are of .rela type */
  320. #define ElfSecF_RELA            2
  321.  
  322.  
  323. struct ElfObject {
  324.   UWORD flags;
  325.   UWORD pad;
  326.   const struct ELFDynSymbols* user_syms;/* User-provided symbols */
  327.   BPTR handle;                          /* ELF file handle */
  328.   char *secnames;                       /* .shstrtab - section names */
  329.   char *symnames;                       /* .strtab - symbol mames */
  330.   struct Elf32_Ehdr *header;            /* the ELF file header */
  331.   struct Elf32_Sym *symtab;             /* .symtab - symbol table */
  332.   uint32 nsyms;                         /* number of symbols */
  333.   uint32 gsyms;                         /* first global symbol */
  334.   struct ELFSection **sections;         /* ELFSection pointers */
  335.   uint32 nsects;                        /* number of sections */
  336. };
  337.  
  338. #define ElfObjB_Relocated       0       /* Object is relocated */
  339. #define ElfObjF_Relocated       1
  340.  
  341. /*** relocnames.c ************************************************************/
  342.  
  343. const char *reloc_name[] = {
  344.   "R_386_NONE",
  345.   "R_386_32",
  346.   "R_386_PC32",
  347.   "R_386_GOT32",
  348.   "R_386_PLT32",
  349.   "R_386_COPY",
  350.   "R_386_GLOB_DAT",
  351.   "R_386_JMP_SLOT",
  352.   "R_386_RELATIVE",
  353.   "R_386_GOTOFF",
  354.   "R_386_GOTPC"
  355. };
  356.  
  357. /*** ppcobject.c *************************************************************/
  358.  
  359.  
  360. static void
  361. freeelfobj(struct ElfObject *elfobj);
  362.  
  363. static BOOL
  364. loadelf32(struct ElfObject *eo,struct Elf32_Shdr *shdrs);
  365.  
  366. static BOOL
  367. loadprogram(struct ElfObject *eo, APTR* entry, BPTR* seg );
  368.  
  369. static void
  370. freeprogram(struct ElfObject *eo);
  371.  
  372. static BPTR
  373. makeseglist( struct ElfObject *eo, APTR text_section );
  374.  
  375. static BOOL
  376. relocate(struct ElfObject *eo);
  377.  
  378. static void*
  379. allocvec( ULONG byteSize, ULONG attributes );
  380.  
  381. static void
  382. freevec( void* memoryBlock );
  383.  
  384. static void*
  385. alloc_dosseg( size_t size );
  386.  
  387. void
  388. free_dosseg( void* addr );
  389.  
  390. static BPTR
  391. opstream(struct ElfObject *eo, const char* name );
  392.  
  393. static BOOL
  394. clstream(struct ElfObject *eo);
  395.  
  396. static BOOL
  397. rdstream(struct ElfObject *eo,void *buf,long len);
  398.  
  399. static long
  400. skstream(struct ElfObject *eo,long offs,long mode);
  401.  
  402. static BOOL
  403. prstream(struct ElfObject *eo,long offs,void *buf,long len);
  404.  
  405. static void*
  406. readsection(struct ElfObject *eo,struct Elf32_Shdr *sh);
  407.  
  408. static struct ELFSection*
  409. progsection(struct ElfObject *eo, struct Elf32_Shdr *sh);
  410.  
  411. static BOOL
  412. common_symbols(struct ElfObject *eo);
  413.  
  414. static BOOL
  415. getrelocs(struct ElfObject *eo,struct Elf32_Shdr *sh);
  416.  
  417. static const char ELFid[4] = {
  418.   0x7f,'E','L','F'
  419. };
  420.  
  421. void*
  422. ELFLoadObject( const char* objname, BPTR* seg, const struct ELFDynSymbols* syms )
  423. {
  424.   struct ElfObject *elfobj = NULL;
  425.  
  426.   /* allocate ElfObject structure */
  427.  
  428.   elfobj = allocvec( sizeof( struct ElfObject ), MEMF_ANY );
  429.  
  430.   if( elfobj != NULL )
  431.   {
  432.     memset(elfobj,0,sizeof(struct ElfObject));
  433.  
  434.     elfobj->user_syms = syms;
  435.  
  436.     elfobj->header = allocvec( sizeof( struct Elf32_Ehdr ), MEMF_ANY );
  437.  
  438.     if( elfobj->header != NULL )
  439.     {
  440.       /* open ELF stream for reading */
  441.  
  442.       elfobj->handle = opstream( elfobj, objname );
  443.  
  444.       if( elfobj->handle != NULL )
  445.       {
  446.         /* read and identify ELF 32bit PowerPC BigEndian header */
  447.  
  448.         if( rdstream( elfobj, elfobj->header, sizeof(struct Elf32_Ehdr) ) )
  449.         {
  450.           struct Elf32_Ehdr *hdr = elfobj->header;
  451.  
  452.           if (!strncmp(hdr->e_ident,ELFid,4) &&
  453.               hdr->e_ident[EI_CLASS]==ELFCLASS32 &&
  454.               hdr->e_ident[EI_DATA]==ELFDATA2MSB &&
  455.               hdr->e_ident[EI_VERSION]==1 && hdr->e_version==1 &&
  456.               (hdr->e_machine==EM_386) && hdr->e_type==ET_REL)
  457.           {
  458.             struct Elf32_Shdr *shdrs;
  459.             ULONG shdrsize = (ULONG) hdr->e_shnum * (ULONG) hdr->e_shentsize;
  460.  
  461.             //Printf("elf32-386-be format recognized\n");
  462.  
  463.             shdrs = allocvec( shdrsize, MEMF_ANY);
  464.  
  465.             if( shdrs != NULL )
  466.             {
  467.               /* read section header table and parse rest of object */
  468.  
  469.               if( prstream( elfobj, hdr->e_shoff, shdrs, shdrsize ) )
  470.               {
  471.                 if( loadelf32( elfobj, shdrs ) )
  472.                 {
  473.                   APTR text_entry;
  474.                   //Printf("ELF object loaded (0x%08lx)\n", elfobj );
  475.                   if( loadprogram( elfobj, &text_entry, seg ) ) {
  476.                     //Printf("Start of PPC code: 0x%08lx\n", text_entry );
  477.                     freevec( shdrs );
  478.                     return (elfobj);
  479.                   }
  480.                 }
  481.               }
  482.               freevec( shdrs );
  483.             }
  484.           }
  485.           else
  486.           {
  487.             //KPrintF( "Not an ELF32-386-BE relocatable object.\n");
  488.           }
  489.         }
  490.       }
  491.       freeelfobj(elfobj);
  492.     }
  493.   }
  494.  
  495.   return (NULL);
  496. }
  497.  
  498.  
  499. void
  500. ELFUnLoadObject( void* obj )
  501. {
  502.   struct ElfObject* elfobj = (struct ElfObject*) obj;
  503.  
  504.   if( obj == NULL )
  505.   {
  506.     return;
  507.   }
  508.  
  509.   if(elfobj->sections != NULL && elfobj->nsects > 0 )
  510.   {
  511.     freeprogram(elfobj);
  512.   }
  513.  
  514.   freeelfobj(elfobj);
  515. }
  516.  
  517. static void freeelfobj(struct ElfObject *elfobj)
  518. /* free all memory connected to an ElfObject */
  519. {
  520.   if (elfobj) {
  521.     if (elfobj->handle)
  522.       clstream(elfobj);
  523.  
  524.     if( elfobj->sections != NULL && elfobj->header != NULL )
  525.     {
  526.       int i;
  527.       
  528.       for( i = 0; i < elfobj->header->e_shnum+1; ++i )
  529.       {
  530.     freevec( elfobj->sections[i] );
  531.       }
  532.     }
  533.     
  534.     freevec(elfobj->secnames);
  535.     freevec(elfobj->symnames);
  536.     freevec(elfobj->header);
  537.     freevec(elfobj->symtab);
  538.     freevec(elfobj->sections);
  539.     freevec(elfobj);
  540.   }
  541. }
  542.  
  543.  
  544. static BOOL loadelf32(struct ElfObject *eo,struct Elf32_Shdr *shdrs)
  545. /* parse ELF object, initialize ElfObject structure */
  546. {
  547.   struct Elf32_Ehdr *hdr = eo->header;
  548.   uint16 i;
  549.  
  550.   if ((eo->secnames = readsection(eo,&shdrs[hdr->e_shstrndx])) &&
  551.       (eo->sections = allocvec((hdr->e_shnum+1)*sizeof(void *),MEMF_ANY))) {
  552.     memset(eo->sections,0,(hdr->e_shnum+1)*sizeof(void *));
  553.     eo->nsects = hdr->e_shnum + 1;  /* +1 section for COMMON symbols */
  554.     for (i=1; i<hdr->e_shnum; i++) {
  555.       switch (shdrs[i].sh_type) {
  556.         case SHT_PROGBITS:
  557.         case SHT_NOBITS:
  558.           if (!(eo->sections[i] = progsection(eo,&shdrs[i])))
  559.             return (FALSE);
  560.           break;
  561.         case SHT_SYMTAB:
  562.           if (!(eo->symnames = readsection(eo,&shdrs[shdrs[i].sh_link]))
  563.               || !(eo->symtab = readsection(eo,&shdrs[i])))
  564.             return (FALSE);
  565.           eo->nsyms = shdrs[i].sh_size / sizeof(struct Elf32_Sym);
  566.           eo->gsyms = shdrs[i].sh_info;
  567.           break;
  568.         default:
  569.           break;
  570.       }
  571.     }
  572.     for (i=1; i<hdr->e_shnum; i++) {
  573.       switch (shdrs[i].sh_type) {
  574.         case SHT_REL:
  575.         case SHT_RELA:
  576.           if (!getrelocs(eo,&shdrs[i]))
  577.             return (FALSE);
  578.           break;
  579.         default:
  580.           break;
  581.       }
  582.     }
  583.     /* allocate space for Common symbols */
  584.     return (common_symbols(eo));
  585.   }
  586.   return (FALSE);
  587. }
  588.  
  589. static BOOL loadprogram(struct ElfObject *eo, APTR* text_section, BPTR* seg )
  590. /* load all sections into memory and relocate them */
  591. {
  592.   static const char *FN = "loadprogram(): ";
  593.   struct ELFSection *s;
  594.   uint8 *p;
  595.   unsigned int i;
  596.  
  597.   for (i=0; i<(eo->nsects-1); i++) {
  598.     if( (s = eo->sections[i]) != NULL ) {
  599.  
  600.       BOOL text   = !strcmp(s->name,".text");     /* .text section flag */
  601.       ULONG size = s->size;
  602.  
  603. //Printf("%sSection '%s' (%ld bytes).\n", FN,s->name, s->size );
  604.       if( size != 0 ) {
  605.         // lcs: In order to be able to make a DOS memory segment out of
  606.         // this later, we allocate 4 extra bytes BEFORE before the actual
  607.         // section. This is handled by alloc_dosseg().
  608.         
  609.         if( (p = alloc_dosseg(size)) != NULL ) {
  610.           s->address = (APTR)p;  /* store section's base address */
  611.           if (!(s->flags & ElfSecF_NOBITS)) {
  612.             /* a PROGBITS section - load it from file */
  613.  
  614.             //Printf("%sreading section %s\n",FN,s->name);
  615.             if (prstream(eo,s->offset,p,s->size)) {
  616.               if (text) {
  617.                 /* get start address of PPC program in .text */
  618.         *text_section = p;
  619.               }
  620.             }
  621.             else {
  622.               *text_section = NULL;
  623.               break;
  624.             }
  625.           }
  626.         }
  627.         else {
  628.           Req("Failed to allocate %ld bytes "
  629.                   "for section '%s'.\n",size,(ULONG)s->name);
  630.           *text_section = NULL;
  631.           break;
  632.         }
  633.       }
  634.     }
  635.   }
  636.  
  637.   if (*text_section != NULL) {
  638.     if (!relocate(eo)) {  /* relocate sections */
  639.       *text_section = NULL;
  640.       freeprogram(eo);
  641.     }
  642.   }
  643.   else
  644.     freeprogram(eo);
  645.  
  646.   /* Build a DOS segment list */
  647.   *seg = makeseglist( eo, *text_section );
  648.  
  649.   if( *seg == 0 )
  650.   {
  651.     *text_section = NULL;
  652.     freeprogram(eo);
  653.   }
  654.  
  655.   //Printf("%sreturning with entry=0x%08lx\n",FN,entry);
  656.   return (*text_section != NULL);
  657. }
  658.  
  659.  
  660. static void freeprogram(struct ElfObject *eo)
  661. {
  662.   struct ELFSection *s;
  663.   unsigned int i;
  664.  
  665.   for (i=0; i<eo->nsects; i++) {
  666.     if( (s = eo->sections[i]) != NULL ) {
  667.       if (s->address) {
  668.         free_dosseg(s->address);
  669.         s->address = NULL;
  670.       }
  671.       freevec( s->relocs );
  672.       s->relocs = NULL;
  673.     }
  674.   }
  675. }
  676.  
  677.  
  678. static BPTR makeseglist( struct ElfObject *eo, APTR text_section )
  679. {
  680.   struct ELFSection *s;
  681.   unsigned int i;
  682.   BPTR  text_segment = 0;
  683.   BPTR  first_segment = NULL;
  684.   BPTR* last_segment_ptr = NULL;
  685.  
  686.   for (i=0; i<eo->nsects; i++) {
  687.     if( (s = eo->sections[i]) != NULL ) {
  688.       if (s->address) {
  689.     BPTR this_segment = MKBADDR( s->address ) - 1;
  690.  
  691.         if( s->address != text_section )
  692.         {
  693.           if( first_segment == 0 )
  694.           {
  695.             first_segment = this_segment;
  696.           }
  697.  
  698.           if( last_segment_ptr != NULL )
  699.           {
  700.             *last_segment_ptr = this_segment;
  701.           }
  702.           
  703.           last_segment_ptr = (BPTR*) ((ULONG) s->address - 4);
  704.         }
  705.         else
  706.         {
  707.           text_segment = this_segment;
  708.         }
  709.       }
  710.     }
  711.   }
  712.  
  713.   if( last_segment_ptr )
  714.   {
  715.     // Make sure the segment list is terminated
  716.     *last_segment_ptr = 0;
  717.   }
  718.  
  719.   if( first_segment && text_segment )
  720.   {
  721.     *(BPTR*)(BADDR(text_segment)) = first_segment;
  722.   }
  723.  
  724.   if( text_segment )
  725.   {
  726.     for (i=0; i<eo->nsects; i++) {
  727.       if( (s = eo->sections[i]) != NULL ) {
  728.     // Segment is not owned by us anymore!
  729.     s->address = NULL;
  730.       }
  731.     }
  732.   }
  733.   
  734. #if 0
  735.   {
  736.     int i = 1;
  737.     BPTR segment;
  738.  
  739.     Printf( "Verifying seglist\n" );
  740.   
  741.     segment = text_segment;
  742.  
  743.     while( segment != 0 )
  744.     {
  745.       Printf( "Segment %ld at 0x%08lx/%08lx, length %ld\n",
  746.               i,
  747.               segment, (ULONG) BADDR( segment ), 
  748.               *(ULONG*)( BADDR( segment - 1 ) ) );
  749.  
  750.       segment = *(ULONG*)( BADDR( segment ) );
  751.       ++i;
  752.     }
  753.   }
  754.  
  755.   return 0;
  756. #endif
  757.  
  758.   return text_segment;
  759. }
  760.  
  761.  
  762. #if 0
  763. static void write_short( void* addr, short value, BOOL little_endian )
  764. {
  765.   if(little_endian)
  766.   {
  767.     value = bswap_short(value);
  768.   }
  769.  
  770.   *((short*) addr) = value;
  771. }
  772. #endif
  773.  
  774. static void write_long( void* addr, long value, BOOL little_endian )
  775. {
  776.   if(little_endian)
  777.   {
  778.     value = bswap_long(value);
  779.   }
  780.  
  781.   *((long*) addr) = value;
  782. }
  783.  
  784. #if 0
  785. static short read_short( void* addr, BOOL little_endian )
  786. {
  787.   short value;
  788.  
  789.   value = *((short*) addr);
  790.  
  791.   if(little_endian)
  792.   {
  793.     value = bswap_short(value);
  794.   }
  795.  
  796.   return value;
  797. }
  798. #endif
  799.  
  800. static long read_long( void* addr, BOOL little_endian )
  801. {
  802.   long value;
  803.  
  804.   value = *((long*) addr);
  805.  
  806.   if(little_endian)
  807.   {
  808.     value = bswap_long(value);
  809.   }
  810.  
  811.   return value;
  812. }
  813.  
  814.  
  815. static BOOL relocate(struct ElfObject *eo)
  816. {
  817.   struct ELFSection *es;
  818.   unsigned int shndx;
  819.  
  820.   for (shndx=0; shndx<(eo->nsects-1); shndx++) {
  821.     if( (es = eo->sections[shndx]) != NULL ) {
  822.       BOOL rela   = (es->flags & ElfSecF_RELA) != 0;
  823.       BOOL little = strcmp(es->name,".text") == 0;
  824.       struct Elf32_Rela *r;
  825.       int i;
  826.  
  827.       //Printf("relocate(): relocating section %s "
  828.       //        "at 0x%08lx\n",es->name,es->address);
  829.  
  830.       for (i=0,r=es->relocs; i<es->nrel; i++,r++) {
  831.         struct Elf32_Sym *sym = &eo->symtab[ELF32_R_SYM(r->r_info)];
  832.         long s; 
  833.         uint8 *p = (uint8 *)es->address + r->r_offset;
  834.  
  835.         switch (sym->st_shndx) {
  836.           case SHN_UNDEF:
  837.           {
  838.             const struct ELFDynSymbols* syms = eo->user_syms;
  839.  
  840.             while( syms->name != NULL )
  841.             {
  842.               if( strcmp( eo->symnames+sym->st_name, syms->name)==0 )
  843.               {
  844.                 s = (ULONG) syms->addr;
  845.                 break;
  846.               }
  847.               
  848.               ++syms;
  849.             }
  850.  
  851.             if( syms->name == NULL )
  852.             {
  853.               Req( "Undefined symbol: '%s'", (ULONG)eo->symnames+sym->st_name);
  854.               return FALSE;
  855.             }
  856.             break;
  857.           }
  858.  
  859.           case SHN_ABS:
  860.             s = sym->st_value;
  861.             break;
  862.         
  863.           case SHN_COMMON:
  864.             Req( "Common symbol: '%s'", (ULONG) eo->symnames+sym->st_name);
  865.             return FALSE;
  866.         
  867.           default:
  868.             s = (long)eo->sections[sym->st_shndx]->address + sym->st_value;
  869.             break;
  870.         }
  871. #if 0
  872.         Printf("*** Now doing relocation type %s "
  873.                 "at %s+%ld referencing "
  874.                 "symbol %s+%ld in section %s at %08lx\n",
  875.                 reloc_name[ELF32_R_TYPE(r->r_info)],es->name,r->r_offset,
  876.                 eo->symnames+sym->st_name,sym->st_value,
  877.                 eo->sections[sym->st_shndx]->name, eo->sections[sym->st_shndx]->address);
  878. #endif
  879.  
  880.         switch (ELF32_R_TYPE(r->r_info)) {
  881.           case R_386_NONE:
  882.             break;
  883.  
  884.           case R_386_32:
  885.             //Printf( "Value: %08lx (raw: %08lx)\n", read_long(p, little), *(long*)p);
  886.             if (rela)
  887.               write_long( p, s + r->r_addend, little );
  888.             else
  889.               write_long( p, read_long( p, little ) + s, little );
  890.             //Printf( "Value: %08lx (raw: %08lx)\n", read_long(p, little), *(long*)p);
  891.             break;
  892.  
  893.           case R_386_PC32:
  894.             //Printf( "Value: %08lx (raw: %08lx)\n", read_long(p, little), *(long*)p);
  895.             if (rela)
  896.               write_long( p, s + r->r_addend - (long) p, little );
  897.             else
  898.               write_long( p, read_long( p, little ) + s - (long) p, little );
  899.             //Printf( "Value: %08lx (raw: %08lx)\n", read_long(p, little), *(long*)p);
  900.             break;
  901.  
  902.           default:
  903.             Req("Relocation type %s\nat %s+%ld referencing\n"
  904.                    "symbol %s+%ld\nis not supported.",
  905.                    (ULONG)reloc_name[ELF32_R_TYPE(r->r_info)],(ULONG)es->name,r->r_offset,
  906.                    (ULONG)eo->symnames+sym->st_name,sym->st_value);
  907.             return (FALSE);
  908.         }
  909.       }
  910.     }
  911.   }
  912.   return (TRUE);
  913. }
  914.  
  915. static void*
  916. allocvec( ULONG byteSize, ULONG attributes )
  917. {
  918.   void* result = AllocVec( byteSize, attributes );
  919. //  Printf( "%08lx: Allocated %ld bytes\n", result, byteSize );
  920.   return result;
  921. }
  922.  
  923. static void
  924. freevec( void* memoryBlock )
  925. {
  926. //  if( memoryBlock != NULL )
  927. //  {
  928. //    Printf( "%08lx: Freeing\n", memoryBlock );
  929. //  }
  930.  
  931.   return FreeVec( memoryBlock );
  932. }
  933.  
  934. static void*
  935. alloc_dosseg( size_t size )
  936. {
  937.   void* address;
  938.  
  939.   /* align size to 32 bytes, add 8 bytes and allocate 32-byte aligned
  940.      memory */
  941.  
  942.   size = ((size+31)&~31);
  943.  
  944.   address = AllocMem( size + 8 + 31, MEMF_ANY );
  945.  
  946.   if( address != NULL )
  947.   {
  948.     Forbid();
  949.     FreeMem( address, size + 8 + 31 );
  950.     address = AllocAbs( size + 8,
  951.             (void*) (((ULONG) (address + 8 + 31) & ~31) - 8) );
  952.     Permit();
  953.   }
  954.  
  955.   if( address != NULL )
  956.   {
  957. //    Printf( "%08lx: Allocated %ld bytes (segment)\n", address, size + 8 );
  958.     *(ULONG*) address = size + 8;
  959.     memset( address + 4, 0, size + 4 );
  960. //    Printf( "alloc_dosseg( %ld ) -> %08lx\n", size, address + 8 );
  961.     return address + 8;
  962.   }
  963.   else
  964.   {
  965.     return NULL;
  966.   }
  967. }
  968.  
  969.  
  970. void
  971. free_dosseg( void* addr )
  972. {
  973. //  Printf( "free_dosseg( %08lx ) -> FreeMem( %08lx, %ld )\n", addr, addr - 8, *(ULONG*)(addr - 8) );
  974.   
  975. //  if( addr != NULL )
  976. //  {
  977. //    Printf( "%08lx: Freeing (seg)\n", addr );
  978. //  }
  979.   
  980.   FreeMem( addr - 8, *(ULONG*)(addr - 8) );
  981. }
  982.  
  983.  
  984. static BPTR
  985. opstream(struct ElfObject *eo __attribute__ ((unused)), const char* name )
  986. {
  987.   BPTR handle = NULL;
  988.  
  989.   if( name != NULL )
  990.   {
  991.     handle = Open( (char*) name, MODE_OLDFILE );
  992.   }
  993.  
  994.   return (handle);
  995. }
  996.  
  997.  
  998. static BOOL
  999. clstream(struct ElfObject *eo)
  1000. {
  1001.   Close( eo->handle );
  1002.   return TRUE;
  1003. }
  1004.  
  1005.  
  1006. static BOOL
  1007. rdstream(struct ElfObject *eo,void *buf,long len)
  1008. {
  1009.   long r;
  1010.   
  1011.   r = Read( eo->handle, buf, len );
  1012.  
  1013.   if( r != len )
  1014.   {
  1015.     return (FALSE);
  1016.   }
  1017.   return (TRUE);
  1018. }
  1019.  
  1020.  
  1021. static long
  1022. skstream(struct ElfObject *eo,long offs,long mode)
  1023. {
  1024.   long r;
  1025.  
  1026.   r = Seek( eo->handle, offs, mode );
  1027.   return (r);
  1028. }
  1029.  
  1030.  
  1031. static BOOL
  1032. prstream(struct ElfObject *eo,long offs,void *buf,long len)
  1033. /* position and read stream */
  1034. {
  1035.   if (skstream(eo,offs,OFFSET_BEGINNING) != -1)
  1036.     return (rdstream(eo,buf,len));
  1037.   return FALSE;
  1038. }
  1039.  
  1040.  
  1041. static void *readsection(struct ElfObject *eo,struct Elf32_Shdr *sh)
  1042. /* allocate memory and read section contents */
  1043. {
  1044.   void *p;
  1045.  
  1046.   if( (p = allocvec(sh->sh_size,MEMF_ANY)) != NULL )
  1047.   {
  1048.     if (prstream(eo,sh->sh_offset,p,sh->sh_size))
  1049.     {
  1050.       return (p);
  1051.     }
  1052.     else
  1053.     {
  1054.       freevec( p );
  1055.     }
  1056.   }
  1057.   return (NULL);
  1058. }
  1059.  
  1060.  
  1061. static struct ELFSection *progsection(struct ElfObject *eo,
  1062.                                       struct Elf32_Shdr *sh)
  1063. /* Create Section structure from Elf32_Shdr. The contents of these     */
  1064. /* sections will be loaded and relocated on demand, e.g. if a new task */
  1065. /* is created. */
  1066. {
  1067.   struct ELFSection *s;
  1068.  
  1069.   if( (s = allocvec(sizeof(struct ELFSection),MEMF_ANY)) != NULL ) {
  1070.     memset(s,0,sizeof(struct ELFSection));
  1071.     s->name = eo->secnames + sh->sh_name;
  1072.     s->flags = sh->sh_type==SHT_NOBITS ? ElfSecF_NOBITS:0;
  1073.     s->alignment = (uint8)sh->sh_addralign;
  1074.     s->offset = sh->sh_offset;
  1075.     s->size = sh->sh_size;
  1076.     return (s);
  1077.   }
  1078.   return (NULL);
  1079. }
  1080.  
  1081.  
  1082. static BOOL common_symbols(struct ElfObject *eo)
  1083. /* Create a and initialize Section structure for Common symbols. */
  1084. {
  1085. //  static const char *FN = "common_symbols(): ";
  1086.   static const char *bssname = ".bss";
  1087.   struct ELFSection *s = NULL;
  1088.   struct Elf32_Sym *sym;
  1089. //  uint16 *relocp;
  1090.   uint32 offset = 0,idx = 0,cnt=0;
  1091.   unsigned int i;
  1092.  
  1093.   /* First try to find a .bss, where Common symbols could be appended */
  1094.   for (i=0; i<(eo->nsects-1); i++) {
  1095.     if( (s = eo->sections[i]) != NULL ) {
  1096.       if (!strcmp(s->name,bssname) && (s->flags & ElfSecF_NOBITS)) {
  1097.         idx = i;
  1098.         offset = s->size;
  1099.         //Printf("%sfound %s at index %ld with size=%ld\n",
  1100.         //        FN,bssname,idx,offset);
  1101.         break;
  1102.       }
  1103.       else
  1104.         s = NULL;
  1105.     }
  1106.   }
  1107.  
  1108.   if (!s) {
  1109.     /* No .bss section present, allocate an own one */
  1110.     if( (s = allocvec(sizeof(struct ELFSection),MEMF_ANY)) != NULL ) {
  1111.       memset(s,0,sizeof(struct ELFSection));
  1112.       s->name = (char*)bssname;
  1113.       s->flags = ElfSecF_NOBITS;
  1114.       s->alignment = 32;
  1115.       offset = 0;
  1116.       idx = eo->nsects-1;
  1117.       eo->sections[idx] = s;
  1118.       //Printf("%screated new %s at index %ld\n",FN,bssname,idx);
  1119.     }
  1120.     else
  1121.       return (FALSE);
  1122.   }
  1123.  
  1124.   /* Ok, search for COMMON symbols now */
  1125.   for (i=1,sym=&eo->symtab[1]; i<eo->nsyms; i++,sym++) {
  1126.     if (sym->st_shndx == SHN_COMMON) {
  1127.       offset = (offset + sym->st_value-1) & ~(sym->st_value-1);
  1128.       sym->st_value = offset;
  1129.       sym->st_shndx = idx;
  1130.       offset += sym->st_size;
  1131.       cnt++;
  1132.     }
  1133.   }
  1134. //  Printf("%sassigned %ld common symbols (%ld bytes)\n",
  1135. //          FN,cnt,offset-s->size);
  1136.   s->size = offset;  /* set new .bss section size */
  1137.  
  1138.   return (TRUE);
  1139. }
  1140.  
  1141.  
  1142. static BOOL getrelocs(struct ElfObject *eo,struct Elf32_Shdr *sh)
  1143. /* read relocation entries for a section */
  1144. {
  1145.   uint32 rsize = sh->sh_entsize;
  1146.   int nrelocs = (int)(sh->sh_size/rsize);
  1147.   struct ELFSection *s = eo->sections[sh->sh_info];
  1148.  
  1149.  
  1150.   s->nrel = nrelocs;
  1151.   if (sh->sh_type == SHT_RELA) {
  1152.     s->flags |= ElfSecF_RELA;
  1153.     if( (s->relocs = readsection(eo,sh)) != NULL )
  1154.       return (TRUE);
  1155.   }
  1156.   else {
  1157.     struct Elf32_Rela *r;
  1158.  
  1159.     if ((r = s->relocs = allocvec(nrelocs*sizeof(struct Elf32_Rela),
  1160.                                   MEMF_ANY)) &&
  1161.         (skstream(eo,sh->sh_offset,OFFSET_BEGINNING) != -1)) {
  1162.       while (nrelocs--) {
  1163.         r->r_addend = 0;
  1164.         if (!rdstream(eo,r,sizeof(struct Elf32_Rel)))
  1165.           return (FALSE);
  1166.         r++;
  1167.       }
  1168.       return (TRUE);
  1169.     }        
  1170.   }
  1171.   return (FALSE);
  1172. }
  1173.